<template>
  <ul class="bx-tree">
    <li 
      v-for="node in data"
      :key="node.value"
      :class="[
        'bx-tree__node',
        {
          'bx-tree__node--expanded': isExpanded(node),
          'bx-tree__node--selected': isSelected(node),
          'bx-tree__node--disabled': node.disabled
        }
      ]"
    >
      <div class="bx-tree__content">
        <BxIcon 
          v-if="node.children && node.children.length"
          :name="isExpanded(node) ? 'chevron-down' : 'chevron-right'"
          class="bx-tree__expand-icon"
          @click.stop="toggleExpand(node)"
        />
        <BxCheckbox
          v-if="checkable"
          :model-value="isChecked(node)"
          :indeterminate="isIndeterminate(node)"
          :disabled="node.disabled"
          @change="handleCheckChange(node)"
        />
        <span 
          class="bx-tree__label"
          @click="handleNodeClick(node)"
        >
          {{ node.label }}
        </span>
      </div>
      <BxTree
        v-if="node.children && node.children.length && isExpanded(node)"
        :data="node.children"
        :checkable="checkable"
        :expand-all="expandAll"
        :selected-value="selectedValue"
        @change="handleChildChange"
      />
    </li>
  </ul>
</template>

<script>
import { ref, computed, watch } from 'vue'
import BxIcon from '../basic/BxIcon.vue'
import BxCheckbox from '../input/BxCheckbox.vue'

export default {
  name: 'BxTree',
  components: {
    BxIcon,
    BxCheckbox
  },
  props: {
    data: {
      type: Array,
      default: () => []
    },
    checkable: {
      type: Boolean,
      default: false
    },
    expandAll: {
      type: Boolean,
      default: false
    },
    selectedValue: {
      type: Array,
      default: () => []
    }
  },
  emits: ['change', 'node-click'],
  setup(props, { emit }) {
    const expandedNodes = ref(new Set())

    // 初始化展开状态
    watch(() => props.expandAll, (newVal) => {
      if (newVal) {
        expandAllNodes(props.data)
      } else {
        expandedNodes.value.clear()
      }
    }, { immediate: true })

    const expandAllNodes = (nodes) => {
      nodes.forEach(node => {
        expandedNodes.value.add(node.value)
        if (node.children) {
          expandAllNodes(node.children)
        }
      })
    }

    const isExpanded = (node) => {
      return expandedNodes.value.has(node.value)
    }

    const toggleExpand = (node) => {
      if (expandedNodes.value.has(node.value)) {
        expandedNodes.value.delete(node.value)
      } else {
        expandedNodes.value.add(node.value)
      }
    }

    const isSelected = (node) => {
      return props.selectedValue.includes(node.value)
    }

    const isChecked = (node) => {
      if (!props.checkable) return false
      return props.selectedValue.includes(node.value)
    }

    const isIndeterminate = (node) => {
      if (!props.checkable || !node.children || node.children.length === 0) return false
      const checkedChildren = node.children.filter(child => props.selectedValue.includes(child.value))
      return checkedChildren.length > 0 && checkedChildren.length < node.children.length
    }

    const handleCheckChange = (node) => {
      const newSelected = new Set(props.selectedValue)
      const isCurrentlyChecked = newSelected.has(node.value)

      if (isCurrentlyChecked) {
        // 取消选中当前节点及其所有子节点
        newSelected.delete(node.value)
        if (node.children) {
          uncheckChildren(node.children, newSelected)
        }
      } else {
        // 选中当前节点及其所有子节点
        newSelected.add(node.value)
        if (node.children) {
          checkChildren(node.children, newSelected)
        }
      }
      emit('change', Array.from(newSelected))
    }

    const checkChildren = (children, selectedSet) => {
      children.forEach(child => {
        selectedSet.add(child.value)
        if (child.children) {
          checkChildren(child.children, selectedSet)
        }
      })
    }

    const uncheckChildren = (children, selectedSet) => {
      children.forEach(child => {
        selectedSet.delete(child.value)
        if (child.children) {
          uncheckChildren(child.children, selectedSet)
        }
      })
    }

    const handleChildChange = (newChildSelected) => {
      emit('change', newChildSelected)
    }

    const handleNodeClick = (node) => {
      emit('node-click', node)
    }

    return {
      expandedNodes,
      isExpanded,
      toggleExpand,
      isSelected,
      isChecked,
      isIndeterminate,
      handleCheckChange,
      handleChildChange,
      handleNodeClick
    }
  }
}
</script>

<style scoped>
.bx-tree {
  list-style: none;
  padding: 0;
  margin: 0;
  font-family: var(--bx-font-family);
  color: var(--bx-text-primary);
}

.bx-tree__node {
  padding: 4px 0;
}

.bx-tree__content {
  display: flex;
  align-items: center;
  padding: 4px 8px;
  cursor: pointer;
  transition: background-color var(--bx-transition-fast);
  border-radius: var(--bx-radius-small);
}

.bx-tree__content:hover {
  background: var(--bx-glass-bg-hover);
}

.bx-tree__node--selected .bx-tree__content {
  background: rgba(0, 122, 255, 0.2);
}

.bx-tree__node--disabled .bx-tree__content {
  opacity: 0.6;
  cursor: not-allowed;
}

.bx-tree__expand-icon {
  font-size: 12px;
  margin-right: 4px;
  transition: transform var(--bx-transition-fast);
}

.bx-tree__node--expanded .bx-tree__expand-icon {
  transform: rotate(90deg);
}

.bx-tree__label {
  flex: 1;
  margin-left: 4px;
}

.bx-tree .bx-checkbox {
  margin-right: 8px;
}

.bx-tree ul {
  padding-left: 16px; /* Indent children */
}
</style>

